#define __LOG4CPP__
#include "../libs/Mylog.h"
#include "../inc/net/TcpServer.h"
#include "../inc/net/Threadpool.h"
#include "../inc/cache/CacheManager.h"
#include "../inc/cache/TimerThread.h"
#include "../inc/local/Configuration.h"
#include "../inc/local/SplitToolCppJieba.hpp"
#include "../inc/local/DictProducer.h"
#include "../inc/local/MyDict.h"
#include "../inc/local/MyTask.h"
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <regex>
#include <queue>
#include <functional>
using namespace std;
using namespace SC;

Threadpool *pthreadpool = NULL;                                                       // 线程池
// 初始化三个单例对象
MyDict *MyDict::_pInstance = new MyDict(); 
Configuration *Configuration::_pInstance = new Configuration("../conf/setting.conf"); 
CacheManager *CacheManager::_pInstance = new CacheManager();  
                               
const char* const ERR_WORD = "Input Args Error..\n      1) INIT DICT..\n     2) START SERVER...\n";


void ConnectionCallBack(const TcpConnectionPtr &ptr)
{
    logInfo("Client:", ptr->address(), ": connected.");
    ptr->send("Welcome to server.");
}

void MessageCallBack(const TcpConnectionPtr &ptr)
{
    string s = ptr->recv();
    logInfo("From client:", ptr->address(), ": get -> ", s);
    cout << s << endl;
    // 查询词的任务交给子线程
    MyTask task(s, ptr);
    pthreadpool->addTask(std::bind(&MyTask::execute, task));
}

void CloseCallBack(const TcpConnectionPtr &ptr)
{
    logInfo("Client connection closed: ", ptr->address());
}

/*
初始化字典的模式
线下读取语料库中的内容，进行创建词典，在进行线上部分之前必须先经过线下部分。
线上根据客户端的内容进行计算，并返回结果
*/

void offline()
{
    // 读取data中的语料库
    MyDict::getpInstance()->initDict(
        Configuration::getpInstance()->getConfigMap()["enCorpus_Dir"], 
        Configuration::getpInstance()->getConfigMap()["chCorpus_Dir"], 
        Configuration::getpInstance()->getConfigMap()["en_Dir"],
        Configuration::getpInstance()->getConfigMap()["ch_Dir"],
        Configuration::getpInstance()->getConfigMap()["cache_dir"]);
}

void online()
{
    // 初始化字典
    MyDict::getpInstance()->initDict(Configuration::getpInstance()->getConfigMap()["cache_dir"]);

    // 启动线程池，用于处理任务
    Threadpool threadpool(
        stoi(Configuration::getpInstance()->getConfigMap()["Threadpool_initnum"]), 
        stoi(Configuration::getpInstance()->getConfigMap()["TaskQueue_size"]));
    pthreadpool = &threadpool;
    pthreadpool->start();

    //启动timerfd线程，每隔一定时间触发事件:内存Cache写回磁盘Cache
    TimerThread timerThread(
        stoi(Configuration::getpInstance()->getConfigMap()["cache_initTime"]), 
        stoi(Configuration::getpInstance()->getConfigMap()["cache_intervalTime"]), 
        std::bind(&CacheManager::periodicUpdateCache, CacheManager::getpInstance()));
    timerThread.start();

    //启动服务器
    TcpServer server(
        Configuration::getpInstance()->getConfigMap()["IP"], 
        stoi(Configuration::getpInstance()->getConfigMap()["Port"]));
    server.setConnectionCB(ConnectionCallBack);
    server.setMessageCB(MessageCallBack);
    server.setCloseCB(CloseCallBack);
    server.start();
}

int main(int argc, char* argv[])
{
    if(argc != 2)
        cout << ERR_WORD << endl;
    else if(atoi(argv[1]) == 1)
         offline();
    else if(atoi(argv[1]) == 2)
    {
        Mylog::getInstance().setPriority(INFO);
        online();
    }
    else 
        cout << ERR_WORD << endl;
    
    return 0;
}